--[[
	File: cl_networking.lua
	For: FTS: Stronghold
	By: Ultra
]]--

GM.Net = {}


--[[ player_extension.lua ]]--

--[[
--local function RecieveStatistics( _, _, _, decoded )
--	if IsValid( decoded.ply ) then 
--		decoded.ply.Statistics = decoded.tbl or {}
--		decoded.ply.StatisticsUpdated = os.date( "%I:%M:%S %p" )
--		if ValidPanel( GAMEMODE.HelpFrame ) and ValidPanel( GAMEMODE.HelpFrame.StatsPanel ) then
--			GAMEMODE.HelpFrame.StatsPanel:PlayerSelected( decoded.ply )
--		end
--	end
--end
--datastream.Hook( "sh_statistics", RecieveStatistics )
]]
net.Receive( "sh_statistics", function( intMsgLen )
	local pPlayer	= net.ReadEntity()
	local tblStats 	= net.ReadTable()

	if not IsValid( pPlayer ) or not pPlayer:IsPlayer() then return end
	pPlayer.Statistics 			= tblStats
	pPlayer.StatisticsUpdated 	= os.date( "%I:%M:%S %p" )
	
	if ValidPanel( GAMEMODE.HelpFrame ) and ValidPanel( GAMEMODE.HelpFrame.StatsPanel ) then
		GAMEMODE.HelpFrame.StatsPanel:PlayerSelected( pPlayer )
	end
end )

--[[
local function RecieveLoadouts( _, _, _, decoded )
	local ply = LocalPlayer()
	ply.Loadouts = nil
	ply.Loadouts = decoded
	GAMEMODE.LoadoutFrame:RefreshLoadouts()
end
if CLIENT then datastream.Hook( "sh_loadouts", RecieveLoadouts ) end
]]
net.Receive( "sh_loadouts", function( intMsgLen )
	local ply = LocalPlayer()
	ply.Loadouts = nil
	ply.Loadouts = net.ReadTable()
	GAMEMODE.LoadoutFrame:RefreshLoadouts()
end )

--[[
local function RecieveLoadout( _, _, _, decoded )
	local ply = LocalPlayer()
	ply.Loadouts = ply.Loadouts or {}
	table.Merge( ply.Loadouts[k], decoded )
	--for k, v in pairs(decoded) do
	--	ply.Loadouts[k] = v
	--end
	GAMEMODE.LoadoutFrame:RefreshLoadouts()
end
if CLIENT then datastream.Hook( "sh_loadout", RecieveLoadout ) end
]]
net.Receive( "sh_loadout", function( intMsgLen )
	local ply = LocalPlayer()
	ply.Loadouts = ply.Loadouts or {}
	table.Merge( ply.Loadouts[k], net.ReadTable() )
	GAMEMODE.LoadoutFrame:RefreshLoadouts()
end )

--[[
local function RecieveLicenses( _, _, _, decoded )
	local ply = LocalPlayer()
	ply.Licenses = nil
	ply.Licenses = decoded
	GAMEMODE.LoadoutFrame:RefreshLicenses()
	GAMEMODE.LoadoutFrame:RefreshHats()
end
if CLIENT then datastream.Hook( "sh_licenses", RecieveLicenses ) end
]]
net.Receive( "sh_licenses", function( intMsgLen )
	local ply = LocalPlayer()
	ply.Licenses = nil
	ply.Licenses = net.ReadTable()
	GAMEMODE.LoadoutFrame:RefreshLicenses()
	GAMEMODE.LoadoutFrame:RefreshHats()
end )

--[[
local function RecieveLicense( _, _, _, decoded )
	local ply = LocalPlayer()
	ply.Licenses = ply.Licenses or { [1]={}, [2]={} }
	table.Merge( ply.Licenses, decoded )
	GAMEMODE.LoadoutFrame:RefreshLicenses()
	GAMEMODE.LoadoutFrame:RefreshHats()
end
if CLIENT then datastream.Hook( "sh_license", RecieveLicense ) end
]]
net.Receive( "sh_license", function( intMsgLen )
	local ply = LocalPlayer()
	ply.Licenses = ply.Licenses or { [1]={}, [2]={} }
	table.Merge( ply.Licenses, net.ReadTable() )
	GAMEMODE.LoadoutFrame:RefreshLicenses()
	GAMEMODE.LoadoutFrame:RefreshHats()
end )

--[[
local function ReceiveMoneyAndMultiplier( um )
	local ply = LocalPlayer()
	if IsValid( ply ) then
		ply:SetMoney( um:ReadFloat() )
		ply:SetMultiplier( um:ReadFloat() )
	end
end
usermessage.Hook( "sh_moneyandmultiplier", ReceiveMoneyAndMultiplier )
]]
net.Receive( "sh_moneyandmultiplier", function( intMsgLen )
	local ply = LocalPlayer()
	if not IsValid( ply ) then return end

	ply:SetMoney( net.ReadFloat() )
	ply:SetMultiplier( net.ReadFloat() )	
end )

--[[
local function RecieveItems( _, _, _, decoded )
	local ply = LocalPlayer()
	ply.Items = nil
	ply.Items = decoded
	GAMEMODE.LoadoutFrame:RefreshLicenses()
end
if CLIENT then datastream.Hook( "sh_items", RecieveItems ) end
]]
net.Receive( "sh_items", function( intMsgLen )
	local ply = LocalPlayer()
	ply.Items = nil
	ply.Items = net.ReadTable()
	GAMEMODE.LoadoutFrame:RefreshLicenses()
end )

--[[
local function RecieveItem( _, _, _, decoded )
	local ply = LocalPlayer()
	ply.Items = ply.Items or {}
	table.Merge( ply.Items, decoded )
	GAMEMODE.LoadoutFrame:RefreshLicenses()
end
if CLIENT then datastream.Hook( "sh_item", RecieveItem ) end
]]
net.Receive( "sh_item", function( intMsgLen )
	local ply = LocalPlayer()
	ply.Items = ply.Items or {}
	table.Merge( ply.Items, net.ReadTable() )
	GAMEMODE.LoadoutFrame:RefreshLicenses()
end )


--[[ cl_gbux.lua ]]--

-- local function RecieveInfo( um )
-- 	GBux.money = um:ReadFloat()
-- 	GBux.multiplier = um:ReadShort()
-- 	GBux.kills = um:ReadShort()
-- 	GBux.deaths = um:ReadShort()
-- end
-- usermessage.Hook( "gbux_recieveinfo", RecieveInfo )
net.Receive( "gbux_recieveinfo", function( intMsgLen )
	if not GBux then return end --wat

 	GBux.money 		= net.ReadFloat()
 	GBux.multiplier = net.ReadInt( 16 )
 	GBux.kills 		= net.ReadInt( 32 )
 	GBux.deaths 	= net.ReadInt( 32 )
end )


--[[ cl_hud.lua ]]--

-- local function RecieveHitDetection( um )
-- 	HitTime = CurTime()
-- 	if GetConVarNumber("sh_hitsound") == 0 then return end
-- 	surface.PlaySound( table.Random(SND_HITDETECTION) )
-- 	surface.PlaySound( table.Random(SND_HITDETECTION) )
-- 	surface.PlaySound( table.Random(SND_HITDETECTION) )
-- end
-- usermessage.Hook( "sh_hitdetection", RecieveHitDetection )
net.Receive( "sh_hitdetection", function( intMsgLen )
	hook.Call( "sh_hitdetection" )
end )


--[[ cl_init.lua ]]--

-- function LocalPlayer_Killed( um )
-- 	GAMEMODE.KillCam.Killer = um:ReadEntity()
-- 	GAMEMODE.KillCam.LastKilled = CurTime()
-- 	GAMEMODE.KillCam.Active = true
-- end
-- usermessage.Hook( "sh_killed", LocalPlayer_Killed )
net.Receive( "sh_killed", function( intMsgLen )
	GAMEMODE.KillCam.Killer 	= net.ReadEntity()
	GAMEMODE.KillCam.LastKilled = CurTime()
	GAMEMODE.KillCam.Active 	= true
end )

-- function LocalPlayer_Spawned( um )
-- 	GAMEMODE.KillCam.Killer = nil
-- 	GAMEMODE.KillCam.Active = false
-- end
-- usermessage.Hook( "sh_spawned", LocalPlayer_Spawned )
net.Receive( "sh_spawned", function( intMsgLen )
 	GAMEMODE.KillCam.Killer = nil
 	GAMEMODE.KillCam.Active = false
end )

-- local function RecieveAdvert( um )
-- 	GAMEMODE.LastAdvertColor = GAMEMODE.CurAdvertColor
-- 	GAMEMODE.LastAdvertMsg = GAMEMODE.CurAdvertMsg
-- 	GAMEMODE.CurAdvertColor = um:ReadShort()
-- 	GAMEMODE.CurAdvertMsg = um:ReadString()
-- 	GAMEMODE.LastAdvertChange = CurTime()
-- 	--surface.PlaySound( "advert.wav" )
-- end
-- usermessage.Hook( "sh_advert", RecieveAdvert )
net.Receive( "sh_advert", function( intMsgLen )
	GAMEMODE.LastAdvertColor 	= GAMEMODE.CurAdvertColor
	GAMEMODE.LastAdvertMsg 		= GAMEMODE.CurAdvertMsg
	GAMEMODE.CurAdvertColor 	= net.ReadInt( 8 )
	GAMEMODE.CurAdvertMsg 		= net.ReadString()
	GAMEMODE.LastAdvertChange 	= CurTime()
end )

-- local function RecieveGameOver()
-- 	GAMEMODE.GameOver = true
-- 	LocalPlayer():SendMessage( "Game over!" )
-- end
-- usermessage.Hook( "sh_gameover", RecieveGameOver )
net.Receive( "sh_gameover", function( intMsgLen )
	GAMEMODE.GameOver = true
	LocalPlayer():SendMessage( "Game over!" )
end )

-- local function RecieveMapList( _, _, _, decoded )
-- 	GAMEMODE.MapList = decoded
-- 	for k, v in pairs(GAMEMODE.MapList) do
-- 		if file.Exists( "materials/maps/"..v.map..".vmt", "GAME" ) then
-- 			GAMEMODE.MapList[k].texture = surface.GetTextureID( "maps/"..v.map )
-- 		end
-- 	end
-- end
-- datastream.Hook( "sh_maplist", RecieveMapList )
net.Receive( "sh_maplist", function( intMsgLen )
	GAMEMODE.MapList = net.ReadTable()

	for k, v in pairs( GAMEMODE.MapList ) do
		if file.Exists( "materials/maps/".. v.map.. ".vmt", "GAME" ) then
			GAMEMODE.MapList[k].texture = surface.GetTextureID( "maps/".. v.map )
		end
	end
end )

-- local function RecieveWinningMap( um )
-- 	GAMEMODE.WinningMap = um:ReadString()
-- 	LocalPlayer():SendMessage( "Map '"..GAMEMODE.WinningMap.."' has won the vote!" )
-- end
-- usermessage.Hook( "sh_winningmap", RecieveWinningMap )
net.Receive( "sh_winningmap", function( intMsgLen )
	GAMEMODE.WinningMap = net.ReadString()
	LocalPlayer():SendMessage( "Map '".. GAMEMODE.WinningMap.. "' has won the vote!" )
end )

-- local function RecieveFadeRagdoll( um )
-- 	local ragdoll = um:ReadEntity()
-- 	if IsValid( ragdoll ) then
-- 		table.insert( GAMEMODE.Ragdolls, {ent=ragdoll,time=CurTime()} )
-- 	end
-- end
-- usermessage.Hook( "sh_faderagdoll", RecieveFadeRagdoll )
net.Receive( "sh_faderagdoll", function( intMsgLen )
	local ragdoll = net.ReadEntity()

	if IsValid( ragdoll ) then
		table.insert( GAMEMODE.Ragdolls, {ent = ragdoll, time = CurTime()} )
	end
end )


--[[ shared.lua ]]--

-- usermessage.Hook( "sh_countdown", function(um) GAMEMODE:CancelCountDown(true) GAMEMODE:StartCountDown( um:ReadShort(), um:ReadString(), um:ReadString() ) end )
net.Receive( "sh_countdown", function( intMsgLen )
	GAMEMODE:CancelCountDown( true )
	GAMEMODE:StartCountDown( net.ReadInt(32), net.ReadString(), net.ReadString() )
end )

-- usermessage.Hook( "sh_cancelcountdown", function() GAMEMODE:CancelCountDown() end )
net.Receive( "sh_cancelcountdown", function( intMsgLen )
	GAMEMODE:CancelCountDown()
end )


--[[ playersounds.lua ]]--

-- function PlayerSounds.PlayerDeath( um )
-- 	local ply = um:ReadEntity()
-- 	local model = um:ReadString()
-- 	if !IsValid( ply ) then return end

-- 	local model = string.lower( ply:GetModel() )
-- 	local index = PlayerSounds.Models[model]
-- 	if !index then
-- 		PlayerSounds.PlaySound( ply, table.Random(PlayerSounds["Male"]["Death"]), false )
-- 	else
-- 		PlayerSounds.PlaySound( ply, table.Random(PlayerSounds[index]["Death"]), false )
-- 	end
-- end
-- usermessage.Hook( "PlayerSounds_PlayerDeath", PlayerSounds.PlayerDeath )
net.Receive( "PlayerSounds_PlayerDeath", function( intMsgLen )
	PlayerSounds.PlayerDeath( net.ReadEntity(), net.ReadString() )
end )

-- function PlayerSounds.ScalePlayerDamage( um )
-- 	local ply = um:ReadEntity()
-- 	local model = um:ReadString()
-- 	local head = um:ReadBool()
-- 	if !IsValid( ply ) then return end

-- 	if head then
-- 		PlayerSounds.PlaySound( ply, table.Random(PlayerSounds.HeadShotSnd), true )
-- 		return
-- 	end

-- 	local index = PlayerSounds.Models[model]
-- 	if !index then
-- 		PlayerSounds.PlaySound( ply, table.Random(PlayerSounds["Male"]["Hurt"]), false )
-- 	else
-- 		PlayerSounds.PlaySound( ply, table.Random(PlayerSounds[index]["Hurt"]), false )
-- 	end
-- end
-- usermessage.Hook( "PlayerSounds_ScalePlayerDamage", PlayerSounds.ScalePlayerDamage )
net.Receive( "PlayerSounds_ScalePlayerDamage", function( intMsgLen )
	PlayerSounds.ScalePlayerDamage( net.ReadEntity(), net.ReadString(), net.ReadBit() == 1 )
end )


--[[ cl_teams.lua ]]--

-- local function TeamCreated( um )
-- 	local index = um:ReadShort()
-- 	local leader = um:ReadEntity() or nil
-- 	local name = um:ReadString() or "<No Name>"
-- 	local color = Color( um:ReadShort() or math.random(50,255), um:ReadShort() or math.random(50,255), um:ReadShort() or math.random(50,255), 255 )
-- 	GAMEMODE.Teams[index] = { Leader=leader, Name=name, Color=color }
-- 	team.SetUp( index, name, color )
-- end
-- usermessage.Hook( "sh_teamcreated", TeamCreated )
net.Receive( "sh_teamcreated", function( intMsgLen )
	local intIndex 	= net.ReadInt( 16 )
	local entLeader = net.ReadEntity()
	local strName 	= net.ReadString() or "<No Name>"
	local colColor 	= Color( net.ReadUInt(8) or math.random(50,255), net.ReadUInt(8) or math.random(50,255), net.ReadUInt(8) or math.random(50,255), 255 )
	
	GAMEMODE.Team:TeamCreated( intIndex, entLeader, strName, colColor )
end )

-- local function TeamDisbanded( um )
-- 	local index = um:ReadShort()
-- 	GAMEMODE.Teams[index] = nil
-- 	team.GetAllTeams()[index] = nil
-- end
-- usermessage.Hook( "sh_teamdisbanded", TeamDisbanded )
net.Receive( "sh_teamdisbanded", function( intMsgLen )
	local intIndex 	= net.ReadInt( 16 )

	GAMEMODE.Team:TeamDisbanded( intIndex )
end )

-- local function TeamLeaderChange( um )
-- 	local index = um:ReadShort()
-- 	if GAMEMODE.Teams[index] then
-- 		GAMEMODE.Teams[index].Leader = um:ReadEntity()
-- 	end
-- end
-- usermessage.Hook( "sh_teamleaderchange", TeamLeaderChange )
net.Receive( "sh_teamleaderchange", function( intMsgLen )
	local intIndex 	= net.ReadInt( 16 )
	local entLeader = net.ReadEntity()

	GAMEMODE.Team:TeamLeaderChange( intIndex, entLeader )
end )


--[[ cl_screeneffects.lua ]]--

-- local function SpawnProtToggle( um )
-- 	SpawnProt = um:ReadBool()
-- 	SpawnProtTime = CurTime()
-- end
-- usermessage.Hook( "sh_spawnprotection", SpawnProtToggle )
net.Receive( "sh_spawnprotection", function( intMsgLen )
	hook.Call( "sh_spawnprotection", {}, net.ReadBit() == 1 )
end )

-- local function FlashToggle( um )
-- 	if !Flashed then
-- 		FlashTime = CurTime()
-- 		FlashDuration = um:ReadFloat()
-- 	else
-- 		local add = um:ReadFloat()
-- 		FlashTime = FlashTime + add * 0.7
-- 		FlashDuration = FlashDuration + add
-- 	end
-- 	Flashed = true
-- end
-- usermessage.Hook( "sh_flashed", FlashToggle )
net.Receive( "sh_flashed", function( intMsgLen )
	hook.Call( "sh_flashed", {}, net.ReadFloat() )
end )


--[[ cl_hats.lua ]]--

-- local function RecieveHat( um )
-- 	local ply = um:ReadEntity()
-- 	if !IsValid( ply ) then return end
-- 	local enable = um:ReadBool()
	
-- 	if enable then
-- 		local hat = um:ReadString()
-- 		local tbl = GAMEMODE.ValidHats[hat]
		
-- 		if !tbl then
-- 			if IsValid( ply.Hat ) then ply.Hat:Remove() end
-- 			ply.Hat = nil
-- 			ply.HatID = nil
-- 			return
-- 		end
		
-- 		ply.HatID = hat
	
-- 		if !IsValid( ply.Hat ) then
-- 			ply.Hat = ents.Create( "prop_physics" )
-- 			ply.Hat:SetModel( tbl.model )
-- 			ply.Hat:Spawn()
-- 			if ply == LocalPlayer() then
-- 				ply.Hat:SetNoDraw( true )
-- 			end
-- 		elseif ply.Hat:GetModel() != tbl.model then
-- 			ply.Hat:SetModel( tbl.model )
-- 		end
		
-- 		ply:SetHatPos( tbl.pos )
-- 		ply:SetHatAng( tbl.ang )
-- 	else
-- 		if IsValid( ply.Hat ) then ply.Hat:Remove() end
-- 		ply.Hat = nil
-- 		ply.HatID = nil
-- 	end
-- end
-- usermessage.Hook( "sh_hat", RecieveHat )
net.Receive( "sh_hat", function( intMsgLen )
	local pPlayer 	= net.ReadEntity()
	local bEnable 	= net.ReadBit() == 1
	local strHat 	= bEnable and net.ReadString() or nil

	hook.Call( "sh_hat", {}, pPlayer, bEnable, strHat )
end )